﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;

namespace iNetScan
{
    public struct IPItem
    {
        public string ip;
        public string status;
        public string mac;
        public string hostname;
    }

    public struct PortItem
    {
        public int port;
        public string status;
    }

    public class Scan
    {
        #region DllImport

        [DllImport("Iphlpapi.dll")]
        private static extern int SendARP(Int32 dest, Int32 host, ref Int64 mac, ref Int32 length);

        [DllImport("Ws2_32.dll")]
        private static extern Int32 inet_addr(string ip);

        #endregion

        #region IPScan

        public static IPItem IPScan(string ip)
        {
            if (IsPrivate(IPToLong(ip))) return ScanPrivateIP(ip);
            else return ScanPublicIP(ip);
        }

        private static IPItem ScanPrivateIP(string ip)
        {
            IPItem Item = new IPItem();
            Item.ip = ip;

            Int64 macinfo = new Int64();
            Int32 length = 6;
            string mac = "";
            try
            {
                SendARP(inet_addr(ip), 0, ref macinfo, ref length);
                if (macinfo == 0) Item.mac = "";
                mac = macinfo.ToString("X12");
                if (mac != "0000" && mac != "000000000000" && mac.Length == 12)
                {
                    Item.mac = new string(new char[] { mac[10], mac[11], '-', mac[8], mac[9], '-', mac[6], mac[7], '-', mac[4], mac[5], '-', mac[2], mac[3], '-', mac[0], mac[1] });
                    Item.status = "在线";
                }
                else
                {
                    Item.mac = "";
                    Item.status = "离线";
                }
            }
            catch
            {
                Item.mac = "";
                Item.status = "离线";
            }

            if (Item.mac != "")
            {
                try
                {
                    IPHostEntry Host = Dns.GetHostEntry(ip);
                    if (Host.HostName != ip) Item.hostname = Host.HostName;
                    else Item.hostname = "";
                }
                catch
                {
                }
            }
            else
            {
                Item.hostname = "";
            }

            return Item;
        }

        private static IPItem ScanPublicIP(string ip)
        {
            IPItem Item = new IPItem();
            Item.ip = ip;
            Item.mac = "";
            Item.hostname = "";

            try
            {                
                if (QT.Net.NetWork.ping(ip))
                {
                    Item.status = "在线";
                }
                else
                {
                    Item.status = "PING不通";
                }
            }
            catch
            {
                Item.status = "错误";
            }

            return Item;
        }

        #endregion

        #region PortScan

        public static PortItem PortScan(string ip, int port)
        {
            PortItem Item = new PortItem();
            Item.port = port;

            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ipport = new IPEndPoint(IPAddress.Parse(ip), port);
            try
            {
                    s.Connect(ipport);
                    if (s.Connected == true) Item.status = "开放";
                    else Item.status = "关闭";
            }
            catch
            {
                Item.status = "关闭";
            }

            return Item;
        }

        #endregion

        #region IP

        public static long IPToLong(string ip_String)
        {
            char[] separator = new char[] { '.' };
            string[] strArray = ip_String.Split(separator);
            long num2 = ((long.Parse(strArray[0]) * 0x100L) * 0x100L) * 0x100L;
            long num3 = (long.Parse(strArray[1]) * 0x100L) * 0x100L;
            long num4 = long.Parse(strArray[2]) * 0x100L;
            long num5 = long.Parse(strArray[3]);
            return (((num2 + num3) + num4) + num5);
        }

        public static string LongToIP(long ip_Int)
        {
            long num = (long)((ip_Int & 0xff000000L) >> 0x18);
            if (num < 0L)
            {
                num += 0x100L;
            }
            long num2 = (ip_Int & 0xff0000L) >> 0x10;
            if (num2 < 0L)
            {
                num2 += 0x100L;
            }
            long num3 = (ip_Int & 0xff00L) >> 8;
            if (num3 < 0L)
            {
                num3 += 0x100L;
            }
            long num4 = ip_Int & 0xffL;
            if (num4 < 0L)
            {
                num4 += 0x100L;
            }
            return (num.ToString() + "." + num2.ToString() + "." + num3.ToString() + "." + num4.ToString());
        }

        public static bool IsPrivate(long ip_Int)
        {
            if (ip_Int >= IPToLong("10.0.0.0") && ip_Int <= IPToLong("10.255.255.255")) return true;
            if (ip_Int >= IPToLong("127.0.0.0") && ip_Int <= IPToLong("127.255.255.255")) return true;
            if (ip_Int >= IPToLong("172.16.0.0") && ip_Int <= IPToLong("172.31.255.255")) return true;
            if (ip_Int >= IPToLong("168.254.0.0") && ip_Int <= IPToLong("168.254.255.255")) return true;
            if (ip_Int >= IPToLong("192.168.0.0") && ip_Int <= IPToLong("192.168.255.255")) return true;

            return false;
        }

        #endregion
    }
}
